package com.hydra.file.controller;

import com.hydra.base.error.BusinessException;
import com.hydra.base.utils.FormatUtil;
import com.hydra.file.constant.FileConstant;
import com.hydra.file.entity.SysFile;
import com.hydra.file.feign.FeignFileService;
import com.hydra.file.services.FileService;
import com.hydra.file.services.SysFileRepository;
import com.hydra.base.annotations.ControllerLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

@Slf4j
@RestController
@RequestMapping(path = "/api/file")
public class FileController {

	@Resource
	private SysFileRepository sysFileRepository;

	@Resource
	private FileService fileService;

	/**
	 * 下载图片
	 * @param input	入参
	 * @return      返回响应结果为保存的id，若抛异常，则code为500
	 */
	@PostMapping(path = "/downloadImage")
	public Long downloadImage(@RequestBody FeignFileService.downloadImage.Input input) throws Exception {
		String url = input.getUrl();
		if(FormatUtil.isEmpty(url)){
			throw new FileNotFoundException("文件下载地址不能为空！");
		}
		//url解密，防止出现特殊字符
		try {
			url = URLDecoder.decode(url, StandardCharsets.UTF_8.toString());
		} catch (UnsupportedEncodingException e) {
			log.error("url解析异常", e);
		}
		try {
			String fileName = input.getFileName();
			String fileSuffix = input.getFileSuffix();
			String filePath = input.getFilePath();
			//组装文件
			SysFile sysFile = fileService.createSysFile(url, fileName, fileSuffix, filePath, FileConstant.FILE_TYPE_IMAGE);
			sysFile.setRemark(input.getRemark());
			//下载文件
			fileService.downloadFile(url, sysFile);

			//持久化
			sysFileRepository.save(sysFile);
			return sysFile.getId();
		} catch (Exception e) {
			throw new BusinessException("下载文件异常", e);
		}
	}

	/**
	 * 上传图片
	 * @param multipartFile		上传的文件
	 * @param fileId		文件id，不为空表示要删除旧文件重新上传
	 * @param fileSuffix	文件的前缀
	 * @param filePath		文件保存的中间路径，如果为空则用当前时间
	 * @param fileName		文件名，为空表示需要设置为uuid
	 * @param fileType		文件类型，最外层的文件夹名称，为空取file，目前可以是image/db/log
	 * @param remark		备注，保存到数据库，暂时没什么用
	 */
	@RequestMapping(path = "/uploadFile")
	public SysFile uploadFile(@RequestParam("file") MultipartFile multipartFile,
							  @RequestParam(name="fileId", required=false) Long fileId,
							  @RequestParam(name="fileSuffix", required=false) String fileSuffix,
							  @RequestParam(name="filePath", required=false) String filePath,
							  @RequestParam(name="fileName", required=false) String fileName,
							  @RequestParam(name="fileType", required=false) String fileType,
							  @RequestParam(name="remark", required=false) String remark) {
		//先删除本地图片再保存文件
		if(fileId != null){
			this.deleteFile(fileId);
		}
		//文件类型
		fileType = FormatUtil.isNullToString(fileType, FileConstant.FILE_TYPE_FILE);
		//上传文件
		SysFile sysFile;
		try {
			InputStream inputStream = multipartFile.getInputStream();
			String realFileName = multipartFile.getOriginalFilename();
			//组装文件,文件名为空，表示需要设置为uuid
			sysFile = fileService.createSysFile(realFileName, fileName, fileSuffix, filePath, fileType);
			if(fileId != null){
				sysFile.setId(fileId);
			}
			sysFile.setRemark(remark);
			//持久化文件
			fileService.persistFile(inputStream, sysFile);
			//持久化
			sysFileRepository.save(sysFile);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException("文件上传异常", e);
		}
		return sysFile;
	}

	/**
	 * 获取文件本地路径
	 * @param id    id
	 */
	@ControllerLog(enable = false)
	@RequestMapping(path = "/image", produces = MediaType.IMAGE_PNG_VALUE)
	public byte[] image(Long id) {
		log.debug("获取的文件id："+id);
		return fileService.getSysFileAsBytes(id);
	}


	/**
	 * 检查文件是否存在
	 * 文件不存在则删除
	 */
	@RequestMapping(path = "/checkAndDelete")
	public boolean checkAndDelete(@RequestBody FeignFileService.checkAndDelete.Input input) {
		Long id = input.getId();
		boolean delete = input.isDelete();
		log.debug("获取的文件id："+id);
		return fileService.moveFileOrDelete(id, delete, input.getRemark(), input.getMovePath());
	}

	/**
	 * 删除图片
	 * @param id    id
	 * @return      返回响应结果为boolean，若抛异常，则code为500
	 */
	@RequestMapping(path = "/deleteFile")
	public Long deleteFile(Long id) {
		log.debug("删除的文件id："+id);
		SysFile sysFile = fileService.deleteSysFile(id);
		return sysFile.getId();
	}

}
